﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using COFE.Core;
using COFE.Core.Utils;
using COFE.Core.Lister;
using COFE.Core.Profile;
using NUnit.Framework;
using COFE.Core.Validater;

namespace COFE.Core.Entry
{
    /// <summary>
    /// Represent an entries, please use COFE.Core.IFileSystemInfo interface instead.
    /// </summary>
    public abstract class FileSystemInfoExA : PropertyHostBase<IFileSystemInfo>,
        IInternalFileSystemInfoExA
    {
        #region Constructors

        /// <summary>
        /// This constructor support primaryPropertyProvider only.
        /// </summary>
        /// <param name="primPropProvider"></param>
        protected FileSystemInfoExA(string listerKey, IPropertyProvider primaryPropProvider)
            : base(primaryPropProvider)
        {
            _thisObj = this;
            if (listerKey != null)
                _listerKey = listerKey;
            else 
            {
                string parsePath;
                COFEPath.ParseFullParseName(primaryPropProvider.
                    GetProperty(FileSystemInfoProperties.FullParseName).ValueAsString, 
                    out _listerKey, out parsePath);
            }
            
            string _parseName = primaryPropProvider.GetParseName();
            _primaryPropertyProvider = primaryPropProvider != null ? primaryPropProvider : NullPropertyProvider.Create();

            //List<IPropertyProvider> entryFilterList = new List<IPropertyProvider>();
            //foreach (var f in manager.SecondaryPropertyProviderFactories)
            //    foreach (var p in f.ConstructPropertyProviders(this))
            //        entryFilterList.Add(p);
            //_secondaryPropertyProviderList.AddRange(entryFilterList);

        }

        #endregion

        #region Methods

        protected IVolume getVolume()
        {
            return COFEShared.VolumeRegistrar.Volumes[_listerKey];;
        }

        protected IVolume getParentVolume()
        {
            return COFEShared.VolumeRegistrar.Volumes[this.Parent.ListerKey];
        }

        public void Delete()
        {
            this.Parent.InternalProperties.DirectoryController.Delete(this, true);
        }

        

        #region Override and Encode Methods
        public override bool Equals(object obj)
        {
            if (obj is IFileSystemInfo)
                return this.ParseName.Equals((obj as IFileSystemInfo).ParseName);
            return false;
        }

        public void Expand()
        {
            IInternalDirectoryInfoExA root = this.getDirectoryRoot(false) as IInternalDirectoryInfoExA;
            if (root != null)
                root.DirectoryLister.Expand(this);
        }


        public void AlertModified(ModifiedAction action)
        {
            if (!IsFileSystem)
            {
                this.Parent.InternalProperties.DirectoryController.NotifyModified(this, action);
                if (Parent != null)
                    (Parent as IDirectoryNotifyFileSystemChanged).AlertChildIsModified(this, this, action);
            }
        }

        public void Refresh()
        {
            PrimaryPropertyProvider.Refresh();
        }


        public override int GetHashCode()
        {
            return this.ParseName.GetHashCode();
        }

        public Guid GetId()
        {
            if (ParseName == ProfileRootDirectoryLister.ProfileRootParsablePath)
                return Guid.Empty;
            return StringUtils<IFileSystemInfo>.GetDeterministicGuid(ParseName);
        }

        public override string ToString()
        {
            return (this is IDirectoryInfo ? "[D] " : "[F] ") + this.ParseName;
        }
        #endregion

        private IDirectoryInfo getParent()
        {
            if (IsPropertySupported(FileSystemInfoProperties.Parent))
                //DBCachePropertyProvider will return it's parent from here.
                return GetProperty(FileSystemInfoProperties.Parent).Value as IDirectoryInfo;
            else
                return getVolume().DirectoryLister.GetParent(this);
        }




        #endregion

        #region Data


        //Cache
        private string _parseName = null;        

        private string _listerKey = null;
        private IPropertyProvider _primaryPropertyProvider = null;

        #endregion


        #region Public Properties

        public IInternalFileSystemInfoExA InternalProperties { get { return this as IInternalFileSystemInfoExA; } }        

        public string ListerKey { get { return _listerKey; } }

        #region PropertyProvider's Properties

        public Guid ParentId
        {
            get
            {
                return String.IsNullOrEmpty(ParentParseName) ? Guid.Empty :
                    StringUtils<IFileSystemInfo>.GetDeterministicGuid(ParentParseName);
            }
        }
        public string ParentParseName { get { return GetProperty(FileSystemInfoProperties.ParentParseName).ValueAsString; } }

        public Guid Id { get { return GetId(); } }

        public IDirectoryInfo Parent { get { return getParent(); } }

        public string Name
        {
            get
            {
                if (IsPropertySupported(FileSystemInfoProperties.Name))
                    return GetProperty(FileSystemInfoProperties.Name).ValueAsString;
                else
                    return COFEPath.GetFileName(ParseName);
            }
        }
        public string Label { get { return GetProperty(FileSystemInfoProperties.Label).ValueAsString; } }
        public string FullName
        {
            get
            {
                if (IsPropertySupported(FileSystemInfoProperties.FullName))
                    return GetProperty(FileSystemInfoProperties.FullName).ValueAsString;
                if (IsPropertySupported(FileSystemInfoProperties.IsFileSystem) &&
                    !GetProperty(FileSystemInfoProperties.IsFileSystem).ValueAsBoolean)
                {
                    Expand();
                    return TempPath;
                }

                throw new NotImplementedException("This item does not implement FullName, and IsFileSystem is not implemented or equal to true.");
            }
        }
        public string TempPath { get { return COFEShared.CurrentUserProfile.Volumes.TempManager.GetTempPath(this); } }
        public string ParseName { get { if (System.String.IsNullOrEmpty(_parseName)) _parseName = this.getParseName(); return _parseName; } }

        public bool IsFolder { get { return (this is DirectoryInfoExA); } }
        public bool IsFileSystem { get { return GetProperty(FileSystemInfoProperties.IsFileSystem).ValueAsBoolean; } }
        public bool Exists { get { return GetProperty(FileSystemInfoProperties.IsExists).ValueAsBoolean; } }

        public FileAttributes Attributes { get { return (FileAttributes)GetProperty(FileSystemInfoProperties.FileAttributes).Value; } }
        public COFEAttributes COFEAttributes { get { return (COFEAttributes)GetProperty(FileSystemInfoProperties.COFEAttributes).Value; } }

        public DateTime CreationTimeUtc { get { return GetProperty(FileSystemInfoProperties.LastWriteTimeUtc).ValueAsUtcDateTime; } }
        public DateTime LastWriteTimeUtc { get { return GetProperty(FileSystemInfoProperties.LastAccessTimeUtc).ValueAsUtcDateTime; } }
        public DateTime LastAccessTimeUtc { get { return GetProperty(FileSystemInfoProperties.CreationTimeUtc).ValueAsUtcDateTime; } }

        public DateTime CreationTime { get { return GetProperty(FileSystemInfoProperties.LastWriteTimeUtc).ValueAsLocalDateTime; } }
        public DateTime LastWriteTime { get { return GetProperty(FileSystemInfoProperties.LastAccessTimeUtc).ValueAsLocalDateTime; } }
        public DateTime LastAccessTime { get { return GetProperty(FileSystemInfoProperties.CreationTimeUtc).ValueAsLocalDateTime; } }

        #endregion

        public IPropertyProvider PrimaryPropertyProvider { get { return _primaryPropertyProvider; } }

        

        #endregion


    }
}
